🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / feature / settings / src / commonMain / kotlin / org / meshtastic / feature / settings / radio / RadioConfigViewModel.kt
Displaying Raw • Download
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/RadioConfigViewModel.kt cd1ebd1ec1470b3968fb7aedfc69975b1b0be5f3 (cd1ebd1e) Text, 58.05 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.settings.radio
Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787androidx.lifecycle.viewModelScope
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.coroutines.CancellationException
Tff7b72import T7ee787kotlinx.coroutines.Job
Tff7b72import T7ee787kotlinx.coroutines.NonCancellable
Tff7b72import T7ee787kotlinx.coroutines.delay
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.combine
Tff7b72import T7ee787kotlinx.coroutines.flow.distinctUntilChanged
Tff7b72import T7ee787kotlinx.coroutines.flow.flatMapLatest
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.flow.launchIn
Tff7b72import T7ee787kotlinx.coroutines.flow.map
Tff7b72import T7ee787kotlinx.coroutines.flow.onEach
Tff7b72import T7ee787kotlinx.coroutines.flow.update
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787kotlinx.coroutines.sync.Mutex
Tff7b72import T7ee787kotlinx.coroutines.sync.withLock
Tff7b72import T7ee787kotlinx.coroutines.withContext
Tff7b72import T7ee787org.jetbrains.compose.resources.StringResource
Tff7b72import T7ee787org.koin.core.annotation.InjectedParam
Tff7b72import T7ee787org.koin.core.annotation.KoinViewModel
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.common.util.nowMillis
Tff7b72import T7ee787org.meshtastic.core.common.util.safeCatching
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.AdminActionsUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.ExportProfileUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.ImportProfileUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.ImportSecurityConfigUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.InstallProfileUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.ProcessRadioResponseUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.RadioConfigUseCase
Tff7b72import T7ee787org.meshtastic.core.domain.usecase.settings.RadioResponseResult
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.MqttConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.MqttProbeStatus
Tff7b72import T7ee787org.meshtastic.core.model.MyNodeInfo
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.model.Position
Tff7b72import T7ee787org.meshtastic.core.repository.AnalyticsPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.FileService
Tff7b72import T7ee787org.meshtastic.core.repository.HomoglyphPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.LocationRepository
Tff7b72import T7ee787org.meshtastic.core.repository.LocationService
Tff7b72import T7ee787org.meshtastic.core.repository.LockdownCoordinator
Tff7b72import T7ee787org.meshtastic.core.repository.LockdownPassphraseStore
Tff7b72import T7ee787org.meshtastic.core.repository.MapConsentPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.MqttManager
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRestartTracker
Tff7b72import T7ee787org.meshtastic.core.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioConfigRepository
Tff7b72import T7ee787org.meshtastic.core.repository.SecurityKeyBackupStore
Tff7b72import T7ee787org.meshtastic.core.repository.ServiceRepository
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.UiText
Tff7b72import T7ee787org.meshtastic.core.resources.cant_shutdown
Tff7b72import T7ee787org.meshtastic.core.resources.key_backup_deleted
Tff7b72import T7ee787org.meshtastic.core.resources.key_backup_not_found
Tff7b72import T7ee787org.meshtastic.core.resources.key_backup_restore_failed
Tff7b72import T7ee787org.meshtastic.core.resources.key_backup_restored
Tff7b72import T7ee787org.meshtastic.core.resources.key_backup_saved
Tff7b72import T7ee787org.meshtastic.core.resources.timeout
Tff7b72import T7ee787org.meshtastic.core.resources.unknown_error
Tff7b72import T7ee787org.meshtastic.core.ui.util.SnackbarManager
Tff7b72import T7ee787org.meshtastic.core.ui.util.getChannelList
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.safeLaunch
Tff7b72import T7ee787org.meshtastic.feature.settings.navigation.ConfigRoute
Tff7b72import T7ee787org.meshtastic.feature.settings.navigation.ModuleRoute
Tff7b72import T7ee787org.meshtastic.proto.AdminMessage
Tff7b72import T7ee787org.meshtastic.proto.Channel
Tff7b72import T7ee787org.meshtastic.proto.ChannelSettings
Tff7b72import T7ee787org.meshtastic.proto.Config
Tff7b72import T7ee787org.meshtastic.proto.DeviceConnectionStatus
Tff7b72import T7ee787org.meshtastic.proto.DeviceMetadata
Tff7b72import T7ee787org.meshtastic.proto.DeviceProfile
Tff7b72import T7ee787org.meshtastic.proto.DeviceUIConfig
Tff7b72import T7ee787org.meshtastic.proto.FileInfo
Tff7b72import T7ee787org.meshtastic.proto.HamParameters
Tff7b72import T7ee787org.meshtastic.proto.HardwareModel
Tff7b72import T7ee787org.meshtastic.proto.LoRaRegionPresetMap
Tff7b72import T7ee787org.meshtastic.proto.LocalConfig
Tff7b72import T7ee787org.meshtastic.proto.LocalModuleConfig
Tff7b72import T7ee787org.meshtastic.proto.MeshPacket
Tff7b72import T7ee787org.meshtastic.proto.ModuleConfig
Tff7b72import T7ee787org.meshtastic.proto.User
Tff7b72import T7ee787kotlin.time.Duration
Tff7b72import T7ee787kotlin.time.Duration.Companion.seconds
Tff7b72internal Tff7b72val Te6edf3MANUAL_CHANNEL_WRITE_DELAYTb4b4b4: Te6edf3Duration Tff7b72= T79c0ff1.Te6edf3seconds
T8b949e/** Data class that represents the current RadioConfig state. */
Tff7b72data Tff7b72class T56d364RadioConfigStateTb4b4b4(
Tff7b72val Te6edf3isLocalTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tff7b72val Te6edf3connectedTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tff7b72val Te6edf3routeTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Tff7b72val Te6edf3metadataTb4b4b4: Te6edf3DeviceMetadata? Tff7b72= Tff7b72nullTb4b4b4,
Tff7b72val Te6edf3userConfigTb4b4b4: Te6edf3User Tff7b72= Te6edf3UserTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72val Te6edf3channelListTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72> Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72val Te6edf3radioConfigTb4b4b4: Te6edf3LocalConfig Tff7b72= Te6edf3LocalConfigTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72val Te6edf3moduleConfigTb4b4b4: Te6edf3LocalModuleConfig Tff7b72= Te6edf3LocalModuleConfigTb4b4b4(Tb4b4b4)Tb4b4b4,
Tff7b72val Te6edf3ringtoneTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Tff7b72val Te6edf3cannedMessageMessagesTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Tff7b72val Te6edf3deviceConnectionStatusTb4b4b4: Te6edf3DeviceConnectionStatus? Tff7b72= Tff7b72nullTb4b4b4,
Tff7b72val Te6edf3deviceUIConfigTb4b4b4: Te6edf3DeviceUIConfig? Tff7b72= Tff7b72nullTb4b4b4,
Tff7b72val Te6edf3fileManifestTb4b4b4: Te6edf3ListTff7b72<Te6edf3FileInfoTff7b72> Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
T8b949e/** Firmware's region→preset legality map (local handshake only); null when unavailable (firmware < 2.8). */
Tff7b72val Te6edf3loraRegionPresetMapTb4b4b4: Te6edf3LoRaRegionPresetMap? Tff7b72= Tff7b72nullTb4b4b4,
T8b949e/** Whether the device being configured is flagged as a licensed (amateur) operator; gates licensed-only presets. */
Tff7b72val Te6edf3localIsLicensedTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tff7b72val Te6edf3responseStateTb4b4b4: Te6edf3ResponseStateTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3EmptyTb4b4b4,
Tff7b72val Te6edf3analyticsAvailableTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72trueTb4b4b4,
Tff7b72val Te6edf3analyticsEnabledTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72trueTb4b4b4,
Tff7b72val Te6edf3nodeDbResetPreserveFavoritesTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)
Tf0883e@KoinViewModel
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffLargeClassTa5d6ff"Tb4b4b4)
Tff7b72open Tff7b72class T56d364RadioConfigViewModelTb4b4b4(
Tf0883e@InjectedParam Tff7b72private Tff7b72val Te6edf3destNumTb4b4b4: Tffa657Int?Tb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioConfigRepositoryTb4b4b4: Te6edf3RadioConfigRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3packetRepositoryTb4b4b4: Te6edf3PacketRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3serviceRepositoryTb4b4b4: Te6edf3ServiceRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3locationRepositoryTb4b4b4: Te6edf3LocationRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3mapConsentPrefsTb4b4b4: Te6edf3MapConsentPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3analyticsPrefsTb4b4b4: Te6edf3AnalyticsPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3homoglyphEncodingPrefsTb4b4b4: Te6edf3HomoglyphPrefsTb4b4b4,
Tff7b72protected Tff7b72val Te6edf3importProfileUseCaseTb4b4b4: Te6edf3ImportProfileUseCaseTb4b4b4,
Tff7b72protected Tff7b72val Te6edf3exportProfileUseCaseTb4b4b4: Te6edf3ExportProfileUseCaseTb4b4b4,
Tff7b72protected Tff7b72val Te6edf3importSecurityConfigUseCaseTb4b4b4: Te6edf3ImportSecurityConfigUseCaseTb4b4b4,
Tff7b72private Tff7b72val Te6edf3installProfileUseCaseTb4b4b4: Te6edf3InstallProfileUseCaseTb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioConfigUseCaseTb4b4b4: Te6edf3RadioConfigUseCaseTb4b4b4,
Tff7b72private Tff7b72val Te6edf3adminActionsUseCaseTb4b4b4: Te6edf3AdminActionsUseCaseTb4b4b4,
Tff7b72private Tff7b72val Te6edf3processRadioResponseUseCaseTb4b4b4: Te6edf3ProcessRadioResponseUseCaseTb4b4b4,
Tff7b72private Tff7b72val Te6edf3locationServiceTb4b4b4: Te6edf3LocationServiceTb4b4b4,
Tff7b72private Tff7b72val Te6edf3fileServiceTb4b4b4: Te6edf3FileServiceTb4b4b4,
Tff7b72private Tff7b72val Te6edf3mqttManagerTb4b4b4: Te6edf3MqttManagerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3lockdownCoordinatorTb4b4b4: Te6edf3LockdownCoordinatorTb4b4b4,
Tff7b72private Tff7b72val Te6edf3securityKeyBackupStoreTb4b4b4: Te6edf3SecurityKeyBackupStoreTb4b4b4,
Tff7b72private Tff7b72val Te6edf3snackbarManagerTb4b4b4: Te6edf3SnackbarManagerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3nodeRestartTrackerTb4b4b4: Te6edf3NodeRestartTrackerTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3lockdownTokenInfo Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3lockdownTokenInfo
Tff7b72val Te6edf3sessionAuthorized Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3sessionAuthorized
Tff7b72val Te6edf3lockdownState Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3lockdownState
Tff7b72fun Td2a8ffsendLockNowTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsendLockNowTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3lockdownCoordinatorTb4b4b4.Te6edf3lockNowTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Submits a lockdown passphrase: enables lockdown (from DISABLED), authenticates ([disable]=false from LOCKED), or
* turns lockdown off ([disable]=true from UNLOCKED).
*/
Tff7b72fun Td2a8ffsubmitLockdownPassphraseTb4b4b4(
Te6edf3passphraseTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3bootsTb4b4b4: Tffa657Int Tff7b72= Te6edf3LockdownPassphraseStoreTb4b4b4.Te6edf3DEFAULT_BOOTSTb4b4b4,
Te6edf3hoursTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3maxSessionSecondsTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3disableTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsubmitLockdownPassphraseTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3lockdownCoordinatorTb4b4b4.Te6edf3submitPassphraseTb4b4b4(Te6edf3passphraseTb4b4b4, Te6edf3bootsTb4b4b4, Te6edf3hoursTb4b4b4, Te6edf3maxSessionSecondsTb4b4b4, Te6edf3disableTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3analyticsAllowedFlow Tff7b72= Te6edf3analyticsPrefsTb4b4b4.Te6edf3analyticsAllowed
Tff7b72fun Td2a8fftoggleAnalyticsAllowedTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3analyticsPrefsTb4b4b4.Te6edf3setAnalyticsAllowedTb4b4b4(Tff7b72!Te6edf3analyticsPrefsTb4b4b4.Te6edf3analyticsAllowedTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3homoglyphEncodingEnabledFlow Tff7b72= Te6edf3homoglyphEncodingPrefsTb4b4b4.Te6edf3homoglyphEncodingEnabled
Tff7b72fun Td2a8fftoggleHomoglyphCharactersEncodingEnabledTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3homoglyphEncodingPrefsTb4b4b4.Te6edf3setHomoglyphEncodingEnabledTb4b4b4(Tff7b72!Te6edf3homoglyphEncodingPrefsTb4b4b4.Te6edf3homoglyphEncodingEnabledTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
T8b949e/** MQTT proxy connection state for the settings UI. */
Tff7b72val Te6edf3mqttConnectionStateTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3MqttConnectionStateTff7b72> Tff7b72= Te6edf3mqttManagerTb4b4b4.Te6edf3mqttConnectionState
T8b949e/** Whether this phone is currently running the MQTT proxy (relaying broker traffic to the connected device). */
Tff7b72val Te6edf3mqttProxyActiveTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3mqttManagerTb4b4b4.Te6edf3proxyActive
T8b949e/**
* Phone-local control over the MQTT proxy that does **not** touch the device's persisted MQTT config. Turning it
* off calls [MqttManager.stop] immediately, cutting the proxy firehose that can saturate the BLE link and MCU on
* nRF devices — no slow device read-modify-write-readback round-trip. Turning it back on resumes proxying using the
* device's current MQTT config (a no-op unless the device has MQTT and proxy-to-client enabled).
*/
Tff7b72fun Td2a8ffsetMqttProxyActiveTb4b4b4(Te6edf3activeTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3activeTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3mqtt Tff7b72= Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3mqtt
Te6edf3mqttManagerTb4b4b4.Te6edf3startProxyTb4b4b4(
Te6edf3enabled Tff7b72= Te6edf3mqttTff7b72?.Te6edf3enabled Tff7b72=Tff7b72= Tff7b72trueTb4b4b4,
Te6edf3proxyToClientEnabled Tff7b72= Te6edf3mqttTff7b72?.Te6edf3proxy_to_client_enabled Tff7b72=Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3mqttManagerTb4b4b4.Te6edf3stopTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3_mqttProbeStatus Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3MqttProbeStatus?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
T8b949e/** Latest result from a [probeMqttConnection] call, or `null` if no probe has been run. */
Tff7b72val Te6edf3mqttProbeStatusTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3MqttProbeStatus?Tff7b72> Tff7b72= Te6edf3_mqttProbeStatusTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3probeJobTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
Tff7b72private Tff7b72val Te6edf3channelUpdateMutex Tff7b72= Te6edf3MutexTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3manualChannelBatchEnqueueing Tff7b72= Tff7b72false
Tff7b72private Tff7b72val Te6edf3manualChannelBatchRequestIds Tff7b72= Te6edf3mutableSetOfTff7b72<Tffa657IntTff7b72>Tb4b4b4(Tb4b4b4)
T8b949e/**
* Run a one-shot reachability/credentials probe against an MQTT broker. Cancels any in-flight probe before starting
* a new one. Result is exposed via [mqttProbeStatus].
*/
Tff7b72fun Td2a8ffprobeMqttConnectionTb4b4b4(Te6edf3addressTb4b4b4: Tffa657StringTb4b4b4, Te6edf3tlsEnabledTb4b4b4: Tffa657BooleanTb4b4b4, Te6edf3usernameTb4b4b4: Tffa657String?Tb4b4b4, Te6edf3passwordTb4b4b4: Tffa657String?Tb4b4b4) Tb4b4b4{
Te6edf3probeJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3_mqttProbeStatusTb4b4b4.Te6edf3value Tff7b72= Te6edf3MqttProbeStatusTb4b4b4.Te6edf3Probing
Te6edf3probeJob Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72val Te6edf3result Tff7b72=
Te6edf3safeCatching Tb4b4b4{ Te6edf3mqttManagerTb4b4b4.Te6edf3probeTb4b4b4(Te6edf3addressTb4b4b4, Te6edf3tlsEnabledTb4b4b4, Te6edf3usernameTb4b4b4, Te6edf3passwordTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3getOrElse Tb4b4b4{ Te6edf3e Tff7b72-Tff7b72>
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffMQTT probe threwTa5d6ff" Tb4b4b4}
Te6edf3MqttProbeStatusTb4b4b4.Te6edf3OtherTb4b4b4(Te6edf3message Tff7b72= Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)
Tb4b4b4}
Te6edf3_mqttProbeStatusTb4b4b4.Te6edf3value Tff7b72= Te6edf3result
Tb4b4b4}
Tb4b4b4}
T8b949e/** Clear the latest probe result (e.g. when the user edits the address). */
Tff7b72fun Td2a8ffclearMqttProbeStatusTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3probeJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3_mqttProbeStatusTb4b4b4.Te6edf3value Tff7b72= Tff7b72null
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3_destNode Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3Node?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3destNodeTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3Node?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_destNode
Tff7b72private Tff7b72val Te6edf3requestIds Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3hashSetOfTff7b72<Tffa657IntTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3requestTimeoutJobs Tff7b72= Te6edf3mutableMapOfTff7b72<Tffa657IntTb4b4b4, Te6edf3JobTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_radioConfigState Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3RadioConfigStateTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3radioConfigStateTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3RadioConfigStateTff7b72> Tff7b72= Te6edf3_radioConfigState
Tff7b72fun Td2a8ffsetPreserveFavoritesTb4b4b4(Te6edf3preserveFavoritesTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3nodeDbResetPreserveFavorites Tff7b72= Te6edf3preserveFavoritesTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3_currentDeviceProfile Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3DeviceProfileTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3currentDeviceProfile
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_currentDeviceProfileTb4b4b4.Te6edf3value
Tff7b72open Tff7b72suspend Tff7b72fun Td2a8ffgetCurrentLocationTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3repositoryTb4b4b4.Te6edf3LocationTff7b72? Tff7b72=
Te6edf3locationServiceTb4b4b4.Te6edf3getCurrentLocationTb4b4b4(Tb4b4b4)
Tff7b72init Tb4b4b4{
Te6edf3nodeRepositoryTb4b4b4.Te6edf3nodeDBbyNum
Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3nodes Tff7b72-Tff7b72> Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Te6edf3nodesTff7b72[Te6edf3destNumTff7b72] Tff7b72else Te6edf3nodesTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3firstOrNullTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3onEach Tb4b4b4{
Te6edf3_destNodeTb4b4b4.Te6edf3value Tff7b72= Tffa657it
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3metadata Tff7b72= Tffa657itTff7b72?.Te6edf3metadataTb4b4b4, Te6edf3localIsLicensed Tff7b72= Tffa657itTff7b72?.Te6edf3userTff7b72?.Te6edf3is_licensed Tff7b72=Tff7b72= Tff7b72trueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3deviceProfileFlowTb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3_currentDeviceProfileTb4b4b4.Te6edf3value Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
T8b949e// Derive isLocal from the immutable destNum and the (possibly changing) myNodeInfo.
T8b949e// flatMapLatest cancels the previous inner flow on every change, so there is
T8b949e// no window where stale local config can leak through.
Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfo
Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3ni Tff7b72-Tff7b72>
Tff7b72val Te6edf3isLocal Tff7b72= Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Te6edf3niTff7b72?.Te6edf3myNodeNumTb4b4b4)
Te6edf3isLocal
Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3isLocal Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3isLocalTb4b4b4) Tb4b4b4{
Te6edf3combineTb4b4b4(
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3channelSetFlowTb4b4b4,
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3localConfigFlowTb4b4b4,
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3moduleConfigFlowTb4b4b4,
Tb4b4b4) Tb4b4b4{ Te6edf3csTb4b4b4, Te6edf3lcTb4b4b4, Te6edf3mc Tff7b72-Tff7b72>
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3isLocal Tff7b72= Tff7b72trueTb4b4b4, Te6edf3channelList Tff7b72= Te6edf3csTb4b4b4.Te6edf3settingsTb4b4b4, Te6edf3radioConfig Tff7b72= Te6edf3lcTb4b4b4, Te6edf3moduleConfig Tff7b72= Te6edf3mcTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Remote admin: clear local config once, then stay idle.
T8b949e// Remote responses arrive via processPacketResponse.
Te6edf3flowOfTb4b4b4(Tffa657UnitTb4b4b4)Tb4b4b4.Te6edf3onEach Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3isLocal Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3channelList Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3radioConfig Tff7b72= Te6edf3LocalConfigTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3moduleConfig Tff7b72= Te6edf3LocalModuleConfigTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3deviceUIConfigFlow
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3uiConfig Tff7b72-Tff7b72> Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3deviceUIConfig Tff7b72= Te6edf3uiConfigTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3fileManifestFlow
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3manifest Tff7b72-Tff7b72> Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3fileManifest Tff7b72= Te6edf3manifestTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3loraRegionPresetMapFlow
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3map Tff7b72-Tff7b72> Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3loraRegionPresetMap Tff7b72= Te6edf3mapTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3serviceRepositoryTb4b4b4.Te6edf3meshPacketFlowTb4b4b4.Te6edf3onEachTb4b4b4(Tff7b72::Te6edf3processPacketResponseTb4b4b4)Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3combineTb4b4b4(Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionStateTb4b4b4, Te6edf3radioConfigStateTb4b4b4) Tb4b4b4{ Te6edf3connStateTb4b4b4, Te6edf3_ Tff7b72-Tff7b72>
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3connected Tff7b72= Te6edf3connState Tff7b72=Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3ConnectedTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
T8b949e// A reboot-applying save can't survive the reboot it triggers: the node drops the transport before the
T8b949e// routing ACK arrives, so the save dialog would otherwise sit at 0% until the 30s request timeout and then
T8b949e// surface a spurious "Timeout" error. The disconnect during an expected-restart window IS the confirmation
T8b949e// the save was persisted (firmware only reboots after saveChanges writes to disk), so resolve the pending
T8b949e// save to the restarting-success the moment the transport drops.
Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionState
Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657it Tff7b72=Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3Connected Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3connected Tff7b72-Tff7b72> Tff7b72if Tb4b4b4(Tff7b72!Te6edf3connectedTb4b4b4) Te6edf3completeRestartingSaveIfPendingTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffRadioConfigViewModel createdTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3myNodeInfoTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3MyNodeInfo?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfo
Tff7b72val Te6edf3myNodeNum
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3myNodeNum
T8b949e/**
* Opens the expected-restart window when a save/action is about to make the LOCALLY CONNECTED node reboot (firmware
* applies most config sections with a reboot a few seconds after the ack). A remote node's reboot doesn't drop our
* transport, so remote destinations never open the window. Called at send time because module saves disable
* Bluetooth on the device immediately — before the save is even acked.
*/
Tff7b72private Tff7b72fun Td2a8ffexpectRestartIfLocalTb4b4b4(Te6edf3behaviorTb4b4b4: Te6edf3RebootBehaviorTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3behavior Tff7b72=Tff7b72= Te6edf3RebootBehaviorTb4b4b4.Te6edf3NEVERTb4b4b4) Tff7b72return
Tff7b72val Te6edf3dest Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Tff7b72if Tb4b4b4(Te6edf3dest Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3expectRestartTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3maxChannels
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3maxChannels Tff7b72?: T79c0ff8
Tff7b72val Te6edf3hasPaFanTb4b4b4: Tffa657Boolean
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72=
Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3userTff7b72?.Te6edf3hw_model Tff7b72in
Te6edf3setOfTb4b4b4(
Tff7b72nullTb4b4b4,
Te6edf3HardwareModelTb4b4b4.Te6edf3UNSETTb4b4b4,
Te6edf3HardwareModelTb4b4b4.Te6edf3BETAFPV_2400_TXTb4b4b4,
Te6edf3HardwareModelTb4b4b4.Te6edf3RADIOMASTER_900_BANDIT_NANOTb4b4b4,
Te6edf3HardwareModelTb4b4b4.Te6edf3RADIOMASTER_900_BANDITTb4b4b4,
Tb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffonClearedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onClearedTb4b4b4(Tb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffRadioConfigViewModel clearedTa5d6ff" Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Routes the User config save: ham onboarding (`set_ham_mode`) when the licensed toggle transitions OFF→ON on the
* locally connected node, [setOwner] otherwise. Routing on the transition — not the toggle state — keeps subsequent
* saves of an already-licensed node on the `set_owner` path, so edits to other owner fields still reach the device
* and the node doesn't reboot on every save (firmware reboots on `set_ham_mode`). The local-node guard is the
* backstop for the UI gate — `set_ham_mode` must never be sent to a remote node.
*/
Tff7b72fun Td2a8ffsaveUserConfigTb4b4b4(Te6edf3userTb4b4b4: Te6edf3UserTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Tff7b72val Te6edf3enablingHam Tff7b72= Te6edf3userTb4b4b4.Te6edf3is_licensed Tff7b72&Tff7b72& Tff7b72!Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3userConfigTb4b4b4.Te6edf3is_licensed
Tff7b72if Tb4b4b4(Te6edf3enablingHam Tff7b72&Tff7b72& Te6edf3destNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Te6edf3setHamModeTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3userTb4b4b4) Tff7b72else Te6edf3setOwnerTb4b4b4(Te6edf3userTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsetHamModeTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3userTb4b4b4: Te6edf3UserTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetHamModeTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3userConfig Tff7b72= Te6edf3userTb4b4b4) Tb4b4b4}
T8b949e// The form's long-name field carries the callsign while licensed (iOS parity).
T8b949e// When meshtastic/protobufs#941 ships, add long_name here.
Te6edf3expectRestartIfLocalTb4b4b4(Te6edf3RebootBehaviorTb4b4b4.Te6edf3ALWAYSTb4b4b4)
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setHamModeTb4b4b4(
Te6edf3destNumTb4b4b4,
Te6edf3HamParametersTb4b4b4(Te6edf3call_sign Tff7b72= Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4, Te6edf3short_name Tff7b72= Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4)Tb4b4b4,
Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Sends a plain `set_owner` with [user]. Prefer [saveUserConfig] for User config screen saves — it routes ham
* onboarding to `set_ham_mode` when the licensed toggle is first enabled; calling this directly bypasses that.
*/
Tff7b72fun Td2a8ffsetOwnerTb4b4b4(Te6edf3userTb4b4b4: Te6edf3UserTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetOwnerTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3userConfig Tff7b72= Te6edf3userTb4b4b4) Tb4b4b4}
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setOwnerTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3userTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4)
Tff7b72fun Td2a8ffupdateChannelsTb4b4b4(Te6edf3newTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4, Te6edf3oldTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetRemoteChannelsTa5d6ff"Tb4b4b4) Tb4b4b4{
T8b949e// Manual channel saves are an ordered batch: only update canonical local state after every write request is
T8b949e// enqueued. Serialize batches so two ordered write plans cannot interleave on the radio link, and diff
T8b949e// each queued save against the canonical list at the moment it starts.
Te6edf3channelUpdateMutexTb4b4b4.Te6edf3withLock Tb4b4b4{
Tff7b72val Te6edf3current Tff7b72= Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3channelListTb4b4b4.Te6edf3ifEmpty Tb4b4b4{ Te6edf3old Tb4b4b4}
Tff7b72val Te6edf3updatePlan Tff7b72= Te6edf3getManualChannelUpdatePlanTb4b4b4(Te6edf3newTb4b4b4, Te6edf3currentTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3updatePlanTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72returnTf0883e@withLock
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3beginManualChannelBatchTb4b4b4(Te6edf3updatePlanTb4b4b4.Te6edf3sizeTb4b4b4)Tb4b4b4) Tff7b72returnTf0883e@withLock
Tff7b72val Te6edf3batchRequestIds Tff7b72= Te6edf3mutableSetOfTff7b72<Tffa657IntTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72try Tb4b4b4{
Te6edf3applyManualChannelUpdatePlanTb4b4b4(
Te6edf3updatePlan Tff7b72= Te6edf3updatePlanTb4b4b4,
Te6edf3currentSettings Tff7b72= Te6edf3currentTb4b4b4,
Te6edf3finalSettings Tff7b72= Te6edf3newTb4b4b4,
Te6edf3writeChannel Tff7b72= Tb4b4b4{ Te6edf3channelTb4b4b4, Te6edf3onRequestId Tff7b72-Tff7b72>
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setRemoteChannelTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3channelTb4b4b4, Te6edf3onRequestIdTb4b4b4)
Tb4b4b4}Tb4b4b4,
Te6edf3registerRequestId Tff7b72= Tb4b4b4{ Te6edf3packetId Tff7b72-Tff7b72>
Te6edf3batchRequestIdsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3packetIdTb4b4b4)
Te6edf3registerManualChannelBatchRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4)
Tb4b4b4}Tb4b4b4,
Te6edf3onInterrupted Tff7b72= Tb4b4b4{ Te6edf3result Tff7b72-Tff7b72>
Te6edf3reconcileInterruptedManualChannelUpdateTb4b4b4(
Te6edf3destNum Tff7b72= Te6edf3destNumTb4b4b4,
Te6edf3oldSettings Tff7b72= Te6edf3currentTb4b4b4,
Te6edf3appliedSettings Tff7b72= Te6edf3resultTb4b4b4.Te6edf3appliedSettingsTb4b4b4,
Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3commitManualChannelSettingsTb4b4b4(Te6edf3destNum Tff7b72= Te6edf3destNumTb4b4b4, Te6edf3oldSettings Tff7b72= Te6edf3currentTb4b4b4, Te6edf3newSettings Tff7b72= Te6edf3newTb4b4b4)
Te6edf3finishManualChannelBatchTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Te6edf3abortManualChannelBatchTb4b4b4(Te6edf3batchRequestIdsTb4b4b4)
Tff7b72throw Te6edf3e
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ThrowableTb4b4b4) Tb4b4b4{
Te6edf3abortManualChannelBatchTb4b4b4(Te6edf3batchRequestIdsTb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffManual channel update failed after enqueueTa5d6ff" Tb4b4b4}
Te6edf3eTb4b4b4.Te6edf3messageTff7b72?.Te6edf3letTb4b4b4(Tff7b72::Te6edf3sendErrorTb4b4b4) Tff7b72?: Te6edf3sendErrorTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3unknown_errorTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffgetManualChannelUpdatePlanTb4b4b4(Te6edf3newTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4, Te6edf3oldTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4)Tb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelTff7b72> Tff7b72=
Te6edf3getChannelListTb4b4b4(Te6edf3newTb4b4b4, Te6edf3oldTb4b4b4)Tb4b4b4.Te6edf3sortedBy Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3index Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffcommitManualChannelSettingsTb4b4b4(
Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3oldSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Te6edf3newSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3withContextTb4b4b4(Te6edf3NonCancellableTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3migrateChannelsByPSKTb4b4b4(Te6edf3oldSettingsTb4b4b4, Te6edf3newSettingsTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3replaceAllSettingsTb4b4b4(Te6edf3newSettingsTb4b4b4)
Tb4b4b4}
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3channelList Tff7b72= Te6edf3newSettingsTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffreconcileInterruptedManualChannelUpdateTb4b4b4(
Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3oldSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Te6edf3appliedSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3withContextTb4b4b4(Te6edf3NonCancellableTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffReconciling interrupted manual channel update appliedSettings=Tffd700${Te6edf3appliedSettingsTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff" Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3migrateChannelsByPSKTb4b4b4(Te6edf3oldSettingsTb4b4b4, Te6edf3appliedSettingsTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3replaceAllSettingsTb4b4b4(Te6edf3appliedSettingsTb4b4b4)
Tb4b4b4}
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3channelList Tff7b72= Te6edf3appliedSettingsTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetConfigTb4b4b4(Te6edf3configTb4b4b4: Te6edf3ConfigTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetConfigTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3radioConfig Tff7b72=
Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3device Tff7b72= Te6edf3configTb4b4b4.Te6edf3device Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3deviceTb4b4b4,
Te6edf3position Tff7b72= Te6edf3configTb4b4b4.Te6edf3position Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3positionTb4b4b4,
Te6edf3power Tff7b72= Te6edf3configTb4b4b4.Te6edf3power Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3powerTb4b4b4,
Te6edf3network Tff7b72= Te6edf3configTb4b4b4.Te6edf3network Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3networkTb4b4b4,
Te6edf3display Tff7b72= Te6edf3configTb4b4b4.Te6edf3display Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3displayTb4b4b4,
T8b949e// LoRa is intentionally NOT applied optimistically: the firmware can clamp or region-swap
T8b949e// (e.g. EU sibling) a LoRa write and applies it live, so the form must reflect the device's
T8b949e// actual value. It is re-read from the device when the LoRa screen is next opened.
Te6edf3bluetooth Tff7b72= Te6edf3configTb4b4b4.Te6edf3bluetooth Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3bluetoothTb4b4b4,
Te6edf3security Tff7b72= Te6edf3configTb4b4b4.Te6edf3security Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3securityTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3expectRestartIfLocalTb4b4b4(Te6edf3configTb4b4b4.Te6edf3saveRebootBehaviorTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setConfigTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3configTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffCyclomaticComplexMethodTa5d6ff"Tb4b4b4)
Tff7b72fun Td2a8ffsetModuleConfigTb4b4b4(Te6edf3configTb4b4b4: Te6edf3ModuleConfigTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetModuleConfigTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3moduleConfig Tff7b72=
Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3mqtt Tff7b72= Te6edf3configTb4b4b4.Te6edf3mqtt Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3mqttTb4b4b4,
Te6edf3serial Tff7b72= Te6edf3configTb4b4b4.Te6edf3serial Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3serialTb4b4b4,
Te6edf3external_notification Tff7b72=
Te6edf3configTb4b4b4.Te6edf3external_notification Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3external_notificationTb4b4b4,
Te6edf3store_forward Tff7b72= Te6edf3configTb4b4b4.Te6edf3store_forward Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3store_forwardTb4b4b4,
Te6edf3range_test Tff7b72= Te6edf3configTb4b4b4.Te6edf3range_test Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3range_testTb4b4b4,
Te6edf3telemetry Tff7b72= Te6edf3configTb4b4b4.Te6edf3telemetry Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3telemetryTb4b4b4,
Te6edf3canned_message Tff7b72= Te6edf3configTb4b4b4.Te6edf3canned_message Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3canned_messageTb4b4b4,
Te6edf3audio Tff7b72= Te6edf3configTb4b4b4.Te6edf3audio Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3audioTb4b4b4,
Te6edf3remote_hardware Tff7b72= Te6edf3configTb4b4b4.Te6edf3remote_hardware Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3remote_hardwareTb4b4b4,
Te6edf3neighbor_info Tff7b72= Te6edf3configTb4b4b4.Te6edf3neighbor_info Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3neighbor_infoTb4b4b4,
Te6edf3ambient_lighting Tff7b72= Te6edf3configTb4b4b4.Te6edf3ambient_lighting Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3ambient_lightingTb4b4b4,
Te6edf3detection_sensor Tff7b72= Te6edf3configTb4b4b4.Te6edf3detection_sensor Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3detection_sensorTb4b4b4,
Te6edf3paxcounter Tff7b72= Te6edf3configTb4b4b4.Te6edf3paxcounter Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3paxcounterTb4b4b4,
Te6edf3statusmessage Tff7b72= Te6edf3configTb4b4b4.Te6edf3statusmessage Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3statusmessageTb4b4b4,
Te6edf3tak Tff7b72= Te6edf3configTb4b4b4.Te6edf3tak Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3takTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3expectRestartIfLocalTb4b4b4(Te6edf3configTb4b4b4.Te6edf3saveRebootBehaviorTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setModuleConfigTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3configTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetRingtoneTb4b4b4(Te6edf3ringtoneTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3ringtone Tff7b72= Te6edf3ringtoneTb4b4b4) Tb4b4b4}
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetRingtoneTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setRingtoneTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3ringtoneTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetCannedMessagesTb4b4b4(Te6edf3messagesTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3cannedMessageMessages Tff7b72= Te6edf3messagesTb4b4b4) Tb4b4b4}
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetCannedMessagesTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setCannedMessagesTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3messagesTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsendAdminRequestTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3route Tff7b72= Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3route
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3route Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4) Tb4b4b4} T8b949e// setter (response is PortNum.ROUTING_APP)
Tff7b72val Te6edf3preserveFavorites Tff7b72= Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3nodeDbResetPreserveFavorites
Tff7b72when Tb4b4b4(Te6edf3routeTb4b4b4) Tb4b4b4{
Te6edf3AdminRouteTb4b4b4.Te6edf3SET_TIMETb4b4b4.Te6edf3name Tff7b72-Tff7b72>
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetTimeTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3adminActionsUseCaseTb4b4b4.Te6edf3setTimeTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4) Tb4b4b4}
Te6edf3AdminRouteTb4b4b4.Te6edf3REBOOTTb4b4b4.Te6edf3name Tff7b72-Tff7b72>
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffrebootTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3expectRestartIfLocalTb4b4b4(Te6edf3RebootBehaviorTb4b4b4.Te6edf3ALWAYSTb4b4b4)
Te6edf3adminActionsUseCaseTb4b4b4.Te6edf3rebootTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Te6edf3AdminRouteTb4b4b4.Te6edf3SHUTDOWNTb4b4b4.Te6edf3name Tff7b72-Tff7b72>
Te6edf3withTb4b4b4(Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3metadataTff7b72?.Te6edf3canShutdown Tff7b72!Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3sendErrorTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3cant_shutdownTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffshutdownTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3adminActionsUseCaseTb4b4b4.Te6edf3shutdownTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3AdminRouteTb4b4b4.Te6edf3FACTORY_RESETTb4b4b4.Te6edf3name Tff7b72-Tff7b72>
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6fffactoryResetTa5d6ff"Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3isLocal Tff7b72= Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3isLocalTb4b4b4) Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3expectRestartTb4b4b4(Tb4b4b4)
Te6edf3adminActionsUseCaseTb4b4b4.Te6edf3factoryResetTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3isLocalTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Te6edf3AdminRouteTb4b4b4.Te6edf3NODEDB_RESETTb4b4b4.Te6edf3name Tff7b72-Tff7b72>
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffnodedbResetTa5d6ff"Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3isLocal Tff7b72= Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4)
T8b949e// Firmware reboots after a nodedb reset, so a local reset drops the transport just like a
T8b949e// factory reset — mark it expected so the UI shows "restarting" instead of a surprise disconnect.
Tff7b72if Tb4b4b4(Te6edf3isLocalTb4b4b4) Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3expectRestartTb4b4b4(Tb4b4b4)
Te6edf3adminActionsUseCaseTb4b4b4.Te6edf3nodedbResetTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3preserveFavoritesTb4b4b4, Te6edf3isLocalTb4b4b4, Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetFixedPositionTb4b4b4(Te6edf3positionTb4b4b4: Te6edf3PositionTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetFixedPositionTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3setFixedPositionTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3positionTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffremoveFixedPositionTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffremoveFixedPositionTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3removeFixedPositionTb4b4b4(Te6edf3destNumTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffimportProfileTb4b4b4(Te6edf3uriTb4b4b4: Te6edf3CommonUriTb4b4b4, Te6edf3onResultTb4b4b4: Tb4b4b4(Te6edf3DeviceProfileTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffimportProfileTa5d6ff"Tb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3profileTb4b4b4: Te6edf3DeviceProfile? Tff7b72= Tff7b72null
Te6edf3fileServiceTb4b4b4.Te6edf3readTb4b4b4(Te6edf3uriTb4b4b4) Tb4b4b4{ Te6edf3source Tff7b72-Tff7b72>
Te6edf3importProfileUseCaseTb4b4b4(Te6edf3sourceTb4b4b4)Tb4b4b4.Te6edf3onSuccess Tb4b4b4{ Te6edf3profile Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4.Te6edf3onFailure Tb4b4b4{ Tff7b72throw Tffa657it Tb4b4b4}
Tb4b4b4}
Te6edf3profileTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3onResultTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffexportProfileTb4b4b4(Te6edf3uriTb4b4b4: Te6edf3CommonUriTb4b4b4, Te6edf3profileTb4b4b4: Te6edf3DeviceProfileTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffexportProfileTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4) Tb4b4b4{ Te6edf3sink Tff7b72-Tff7b72>
Te6edf3exportProfileUseCaseTb4b4b4(Te6edf3sinkTb4b4b4, Te6edf3profileTb4b4b4)Tb4b4b4.Te6edf3onSuccess Tb4b4b4{ T8b949e/* Success */ Tb4b4b4}Tb4b4b4.Te6edf3onFailure Tb4b4b4{ Tff7b72throw Tffa657it Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e/** Whether an encrypted key backup exists for the node currently being configured. */
Tff7b72fun Td2a8ffsecurityKeyBackupExistsTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3nodeNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return Tff7b72false
Tff7b72return Te6edf3securityKeyBackupStoreTb4b4b4.Te6edf3getTb4b4b4(Te6edf3nodeNumTb4b4b4) Tff7b72!Tff7b72= Tff7b72null
Tb4b4b4}
T8b949e/** Saves the node's current public/private keys to OS-backed encrypted storage, keyed by node number. */
Tff7b72fun Td2a8ffbackupSecurityKeysTb4b4b4(Te6edf3securityConfigTb4b4b4: Te6edf3ConfigTb4b4b4.Te6edf3SecurityConfigTb4b4b4, Te6edf3onCompleteTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3nodeNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffbackupSecurityKeysTa5d6ff"Tb4b4b4) Tb4b4b4{
T8b949e// Guard against the empty SecurityConfig() fallback: backing up blanks and later restoring them would
T8b949e// overwrite the device's real keys.
Tff7b72if Tb4b4b4(Te6edf3securityConfigTb4b4b4.Te6edf3public_keyTb4b4b4.Te6edf3size Tff7b72=Tff7b72= T79c0ff0 Tff7b72|Tff7b72| Te6edf3securityConfigTb4b4b4.Te6edf3private_keyTb4b4b4.Te6edf3size Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(Te6edf3message Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3key_backup_restore_failedTb4b4b4)Tb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72returnTf0883e@safeLaunch
Tb4b4b4}
Te6edf3securityKeyBackupStoreTb4b4b4.Te6edf3saveTb4b4b4(
Te6edf3nodeNum Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3publicKeyBase64 Tff7b72= Te6edf3securityConfigTb4b4b4.Te6edf3public_keyTb4b4b4.Te6edf3base64Tb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3privateKeyBase64 Tff7b72= Te6edf3securityConfigTb4b4b4.Te6edf3private_keyTb4b4b4.Te6edf3base64Tb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3timestamp Tff7b72= Te6edf3nowMillisTb4b4b4,
Tb4b4b4)
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(Te6edf3message Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3key_backup_savedTb4b4b4)Tb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3onCompleteTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e/** Restores the previously backed-up keys for this node and pushes them to the device via admin config. */
Tff7b72fun Td2a8ffrestoreSecurityKeysTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3nodeNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffrestoreSecurityKeysTa5d6ff"Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3stored Tff7b72= Te6edf3securityKeyBackupStoreTb4b4b4.Te6edf3getTb4b4b4(Te6edf3nodeNumTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3stored Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(Te6edf3message Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3key_backup_not_foundTb4b4b4)Tb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72returnTf0883e@safeLaunch
Tb4b4b4}
Te6edf3importSecurityConfigUseCaseTb4b4b4(Te6edf3storedTb4b4b4)
Tb4b4b4.Te6edf3onSuccess Tb4b4b4{
Te6edf3setConfigTb4b4b4(Te6edf3ConfigTb4b4b4(Te6edf3security Tff7b72= Tffa657itTb4b4b4)Tb4b4b4)
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(Te6edf3message Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3key_backup_restoredTb4b4b4)Tb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3onFailure Tb4b4b4{
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(
Te6edf3message Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3key_backup_restore_failedTb4b4b4)Tb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e/** Deletes the encrypted key backup for this node, if any. */
Tff7b72fun Td2a8ffdeleteSecurityKeyBackupTb4b4b4(Te6edf3onCompleteTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3nodeNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffdeleteSecurityKeyBackupTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3securityKeyBackupStoreTb4b4b4.Te6edf3deleteTb4b4b4(Te6edf3nodeNumTb4b4b4)
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(Te6edf3message Tff7b72= Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3key_backup_deletedTb4b4b4)Tb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3onCompleteTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffinstallProfileTb4b4b4(Te6edf3protobufTb4b4b4: Te6edf3DeviceProfileTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffinstallProfileTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3installProfileUseCaseTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3protobufTb4b4b4, Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3userTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffclearPacketResponseTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3clearRequestIdsTb4b4b4(Tb4b4b4)
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3EmptyTb4b4b4) Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Sets the initial loading state for remote config sub-screens. Must be called before the first
* `collectAsStateWithLifecycle` read so the LoadingOverlay is visible from the very first composition frame.
*/
Tff7b72fun Td2a8ffensureLoadingForRemoteTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3state Tff7b72= Te6edf3_radioConfigStateTb4b4b4.Te6edf3value
Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3stateTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3EmptyTb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e/** Refreshes a config route while keeping the connect-time local snapshot visible. */
Tff7b72fun Td2a8ffloadConfigRouteTb4b4b4(Te6edf3routeTb4b4b4: Te6edf3EnumTff7b72<Tff7b72*Tff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3setResponseStateLoadingTb4b4b4(Te6edf3route Tff7b72= Te6edf3routeTb4b4b4, Te6edf3showOverlay Tff7b72= Te6edf3destNum Tff7b72!Tff7b72= Tff7b72nullTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffsetResponseStateLoadingTb4b4b4(Te6edf3routeTb4b4b4: Te6edf3EnumTff7b72<Tff7b72*Tff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3setResponseStateLoadingTb4b4b4(Te6edf3route Tff7b72= Te6edf3routeTb4b4b4, Te6edf3showOverlay Tff7b72= Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsetResponseStateLoadingTb4b4b4(Te6edf3routeTb4b4b4: Te6edf3EnumTff7b72<Tff7b72*Tff7b72>Tb4b4b4, Te6edf3showOverlayTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
T8b949e// A module without a per-module get (no ModuleConfigType, e.g. MeshBeacon) reads from the connect-time config
T8b949e// sync — just select the route and render, skipping the loading/request round-trip that would never complete.
Tff7b72if Tb4b4b4(Te6edf3route Tff7b72is Te6edf3ModuleRoute Tff7b72&Tff7b72& Tff7b72!Te6edf3routeTb4b4b4.Te6edf3refreshableTb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3route Tff7b72= Te6edf3routeTb4b4b4.Te6edf3nameTb4b4b4, Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3EmptyTb4b4b4) Tb4b4b4}
Tff7b72return
Tb4b4b4}
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3route Tff7b72= Te6edf3routeTb4b4b4.Te6edf3nameTb4b4b4, Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4(Te6edf3showOverlay Tff7b72= Te6edf3showOverlayTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72when Tb4b4b4(Te6edf3routeTb4b4b4) Tb4b4b4{
Te6edf3ConfigRouteTb4b4b4.Te6edf3USER Tff7b72-Tff7b72>
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetOwnerTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getOwnerTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4) Tb4b4b4}
Te6edf3ConfigRouteTb4b4b4.Te6edf3CHANNELS Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetChannel0Ta5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getChannelTb4b4b4(Te6edf3destNumTb4b4b4, T79c0ff0Tb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetLoraConfigTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getConfigTb4b4b4(
Te6edf3destNumTb4b4b4,
Te6edf3AdminMessageTb4b4b4.Te6edf3ConfigTypeTb4b4b4.Te6edf3LORA_CONFIGTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4,
Tb4b4b4)
Tb4b4b4}
T8b949e// channel editor is synchronous, so we don't use requestIds as total
Te6edf3setResponseStateTotalTb4b4b4(Te6edf3maxChannels Tff7b72+ T79c0ff1Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3AdminRoute Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetSessionKeyConfigTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getConfigTb4b4b4(
Te6edf3destNumTb4b4b4,
Te6edf3AdminMessageTb4b4b4.Te6edf3ConfigTypeTb4b4b4.Te6edf3SESSIONKEY_CONFIGTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3setResponseStateTotalTb4b4b4(T79c0ff2Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3ConfigRoute Tff7b72-Tff7b72> Te6edf3loadConfigRouteTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3routeTb4b4b4)
Tff7b72is Te6edf3ModuleRoute Tff7b72-Tff7b72> Te6edf3loadModuleRouteTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3routeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffloadConfigRouteTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3routeTb4b4b4: Te6edf3ConfigRouteTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3route Tff7b72=Tff7b72= Te6edf3ConfigRouteTb4b4b4.Te6edf3LORATb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetChannel0ForLoraTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getChannelTb4b4b4(Te6edf3destNumTb4b4b4, T79c0ff0Tb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3route Tff7b72=Tff7b72= Te6edf3ConfigRouteTb4b4b4.Te6edf3NETWORKTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetConnectionStatusTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getDeviceConnectionStatusTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetConfigTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getConfigTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3routeTb4b4b4.Te6edf3typeTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffloadModuleRouteTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3routeTb4b4b4: Te6edf3ModuleRouteTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3route Tff7b72=Tff7b72= Te6edf3ModuleRouteTb4b4b4.Te6edf3CANNED_MESSAGETb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetCannedMessagesTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getCannedMessagesTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3route Tff7b72=Tff7b72= Te6edf3ModuleRouteTb4b4b4.Te6edf3EXT_NOTIFICATIONTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetRingtoneTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getRingtoneTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetModuleConfigTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getModuleConfigTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3routeTb4b4b4.Te6edf3typeTb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffshouldReportLocationTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657Int?Tb4b4b4) Tff7b72= Te6edf3mapConsentPrefsTb4b4b4.Te6edf3shouldReportLocationTb4b4b4(Te6edf3nodeNumTb4b4b4)
Tff7b72fun Td2a8ffsetShouldReportLocationTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657Int?Tb4b4b4, Te6edf3shouldReportLocationTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3mapConsentPrefsTb4b4b4.Te6edf3setShouldReportLocationTb4b4b4(Te6edf3nodeNumTb4b4b4, Te6edf3shouldReportLocationTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsetResponseStateTotalTb4b4b4(Te6edf3totalTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4) Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3stateTb4b4b4.Te6edf3responseStateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3total Tff7b72= Te6edf3totalTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3state T8b949e// Return the unchanged state for other response states
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffbeginManualChannelBatchTb4b4b4(Te6edf3totalTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hasUnrelatedPendingRequestTb4b4b4(Tb4b4b4) Tff7b72|Tff7b72| Te6edf3hasPendingRequestRegistrationTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffManual channel update skipped while another radio request is pendingTa5d6ff" Tb4b4b4}
Tff7b72return Tff7b72false
Tb4b4b4}
Te6edf3manualChannelBatchEnqueueing Tff7b72= Tff7b72true
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3route Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4(Te6edf3total Tff7b72= Te6edf3totalTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72return Tff7b72true
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8fffinishManualChannelBatchTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3manualChannelBatchEnqueueing Tff7b72= Tff7b72false
Tff7b72if Tb4b4b4(Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3setResponseStateSuccessTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffabortManualChannelBatchTb4b4b4(Te6edf3batchRequestIdsTb4b4b4: Te6edf3SetTff7b72<Tffa657IntTff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3manualChannelBatchEnqueueing Tff7b72= Tff7b72false
Te6edf3removeRequestIdsTb4b4b4(Te6edf3batchRequestIdsTb4b4b4)
Tb4b4b4}
T8b949e/**
* True while a manual channel batch is in flight — from enqueue through the ack-wait that outlives
* [finishManualChannelBatch]. [manualChannelBatchEnqueueing] alone only covers the enqueue phase, so pending batch
* request ids are the authoritative signal that a batch (not a reboot-applying save) owns the current Loading
* state.
*/
Tff7b72private Tff7b72fun Td2a8ffmanualChannelBatchInFlightTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3manualChannelBatchEnqueueing Tff7b72|Tff7b72| Te6edf3manualChannelBatchRequestIdsTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffcompleteSetRequestOrProgressBatchTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3manualChannelBatchEnqueueingTb4b4b4) Tb4b4b4{
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3setResponseStateSuccessTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Resolves a pending SAVE response to success ("node is restarting") when a restart is expected. Called on the
* transport-drop edge (the reboot) and as the request-timeout backstop. Scoped to saves (route is empty; gets keep
* their route set) and gated on [NodeRestartTracker.restartExpected] so a genuine unexpected disconnect still
* surfaces normally. Clears request ids first so the pending 30s timeout can't later flip success back to error.
*/
Tff7b72private Tff7b72fun Td2a8ffcompleteRestartingSaveIfPendingTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3restartExpectedTb4b4b4.Te6edf3valueTb4b4b4) Tff7b72return
T8b949e// A manual channel batch shares the save shape (empty route + Loading) but never reboots the node; a stale
T8b949e// restart window must not flip an in-flight batch to success. The batch stays in flight through its ack-wait,
T8b949e// past finishManualChannelBatch, so key off its pending request ids — not just the enqueue flag.
Tff7b72if Tb4b4b4(Te6edf3manualChannelBatchInFlightTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72return
Tff7b72val Te6edf3state Tff7b72= Te6edf3radioConfigStateTb4b4b4.Te6edf3value
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3Loading Tff7b72&Tff7b72& Te6edf3stateTb4b4b4.Te6edf3routeTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3clearRequestIdsTb4b4b4(Tb4b4b4)
Te6edf3setResponseStateSuccessTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72protected Tff7b72fun Td2a8ffsetResponseStateSuccessTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4) Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3SuccessTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3state T8b949e// Return the unchanged state for other response states
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72protected Tff7b72fun Td2a8ffsendErrorTb4b4b4(Te6edf3errorTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Te6edf3setResponseStateErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3DynamicStringTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4)
Tff7b72protected Tff7b72fun Td2a8ffsendErrorTb4b4b4(Te6edf3idTb4b4b4: Te6edf3StringResourceTb4b4b4) Tff7b72= Te6edf3setResponseStateErrorTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3idTb4b4b4)Tb4b4b4)
Tff7b72protected Tff7b72fun Td2a8ffsendErrorTb4b4b4(Te6edf3errorTb4b4b4: Te6edf3UiTextTb4b4b4) Tff7b72= Te6edf3setResponseStateErrorTb4b4b4(Te6edf3errorTb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffsetResponseStateErrorTb4b4b4(Te6edf3errorTb4b4b4: Te6edf3UiTextTb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3ErrorTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffincrementCompletedTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3increment Tff7b72= Te6edf3stateTb4b4b4.Te6edf3responseStateTb4b4b4.Te6edf3completed Tff7b72+ T79c0ff1
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3stateTb4b4b4.Te6edf3responseStateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3completed Tff7b72= Te6edf3incrementTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3state T8b949e// Return the unchanged state for other response states
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffregisterRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3requestTimeoutJobsTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3packetIdTb4b4b4)Tff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3requestIdsTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3withPacketIdTb4b4b4(Te6edf3packetIdTb4b4b4) Tb4b4b4}
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3total Tff7b72= Te6edf3maxOfTb4b4b4(Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3sizeTb4b4b4, Te6edf3stateTb4b4b4.Te6edf3responseStateTb4b4b4.Te6edf3totalTb4b4b4)
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3responseState Tff7b72= Te6edf3stateTb4b4b4.Te6edf3responseStateTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3total Tff7b72= Te6edf3totalTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3route Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4, T8b949e// setter (response is PortNum.ROUTING_APP)
Te6edf3responseState Tff7b72= Te6edf3ResponseStateTb4b4b4.Te6edf3LoadingTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3requestTimeout Tff7b72= T79c0ff3T79c0ff0.Te6edf3seconds
Te6edf3requestTimeoutJobsTff7b72[Te6edf3packetIdTff7b72] Tff7b72=
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffrequestTimeoutTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3delayTb4b4b4(Te6edf3requestTimeoutTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3packetIdTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// Capture batch membership before removeRequestId drops the last id and empties the batch set.
Tff7b72val Te6edf3timedOutBatchRequest Tff7b72= Te6edf3packetId Tff7b72in Te6edf3manualChannelBatchRequestIds
Te6edf3removeRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// A save that reboots the node races the reboot against its ACK; a timeout here during an
T8b949e// expected restart means the reboot won — treat it as the restarting-success, not an error.
T8b949e// A manual channel batch never reboots, so exclude it even inside a stale restart window.
Tff7b72if Tb4b4b4(
Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3restartExpectedTb4b4b4.Te6edf3value Tff7b72&Tff7b72&
Tff7b72!Te6edf3timedOutBatchRequest Tff7b72&Tff7b72&
Tff7b72!Te6edf3manualChannelBatchInFlightTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72&
Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3routeTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Te6edf3setResponseStateSuccessTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendErrorTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3timeoutTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffregisterManualChannelBatchRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3manualChannelBatchRequestIdsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3packetIdTb4b4b4)
Te6edf3registerRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhasUnrelatedPendingRequestTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72= Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657it Tff7b72!in Te6edf3manualChannelBatchRequestIds Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhasPendingRequestRegistrationTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72= Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72&
Te6edf3manualChannelBatchRequestIdsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72&
Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3responseState Tff7b72is Te6edf3ResponseStateTb4b4b4.Te6edf3Loading
Tff7b72private Tff7b72fun Td2a8ffclearRequestIdsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3requestTimeoutJobsTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3forEach Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3cancelTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3requestTimeoutJobsTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Te6edf3manualChannelBatchRequestIdsTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Te6edf3requestIdsTb4b4b4.Te6edf3value Tff7b72= Te6edf3hashSetOfTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffremoveRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3requestTimeoutJobsTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3packetIdTb4b4b4)Tff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3manualChannelBatchRequestIdsTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3packetIdTb4b4b4)
Te6edf3requestIdsTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3withoutPacketIdTb4b4b4(Te6edf3packetIdTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffremoveRequestIdsTb4b4b4(Te6edf3packetIdsTb4b4b4: Te6edf3SetTff7b72<Tffa657IntTff7b72>Tb4b4b4) Tb4b4b4{
Te6edf3packetIdsTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3requestTimeoutJobsTb4b4b4.Te6edf3removeTb4b4b4(Tffa657itTb4b4b4)Tff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3manualChannelBatchRequestIdsTb4b4b4.Te6edf3removeAllTb4b4b4(Te6edf3packetIdsTb4b4b4)
Te6edf3requestIdsTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3ids Tff7b72-Tff7b72> Te6edf3idsTb4b4b4.Te6edf3withoutPacketIdsTb4b4b4(Te6edf3packetIdsTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffprocessPacketResponseTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3destNodeTb4b4b4.Te6edf3valueTff7b72?.Te6edf3num Tff7b72?: Tff7b72return
Tff7b72val Te6edf3result Tff7b72= Te6edf3processRadioResponseUseCaseTb4b4b4(Te6edf3packetTb4b4b4, Te6edf3destNumTb4b4b4, Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4) Tff7b72?: Tff7b72return
Tff7b72val Te6edf3route Tff7b72= Te6edf3radioConfigStateTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3route
Tff7b72when Tb4b4b4(Te6edf3resultTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3Error Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3sendErrorTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3messageTb4b4b4)
T8b949e// Abort the AdminRoute flow — do not fire the destructive action
T8b949e// (reboot/shutdown/factory_reset) if the metadata preflight failed.
Tff7b72return
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3Success Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3routeTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3data Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decodedTff7b72!!
Te6edf3removeRequestIdTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3request_idTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3completeSetRequestOrProgressBatchTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3Metadata Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3metadata Tff7b72= Te6edf3resultTb4b4b4.Te6edf3metadataTb4b4b4) Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3ChannelResponse Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3response Tff7b72= Te6edf3resultTb4b4b4.Te6edf3channel
T8b949e// Stop once we get to the first disabled entry
Tff7b72if Tb4b4b4(Te6edf3responseTb4b4b4.Te6edf3role Tff7b72!Tff7b72= Te6edf3ChannelTb4b4b4.Te6edf3RoleTb4b4b4.Te6edf3DISABLEDTb4b4b4) Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3channelList Tff7b72=
Te6edf3stateTb4b4b4.Te6edf3channelListTb4b4b4.Te6edf3toMutableListTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Tff7b72val Te6edf3index Tff7b72= Te6edf3responseTb4b4b4.Te6edf3index
Tff7b72val Te6edf3settings Tff7b72= Te6edf3responseTb4b4b4.Te6edf3settings Tff7b72?: Te6edf3ChannelSettingsTb4b4b4(Tb4b4b4)
T8b949e// Make sure list is large enough
Tff7b72while Tb4b4b4(Te6edf3size Tff7b72<Tff7b72= Te6edf3indexTb4b4b4) Te6edf3addTb4b4b4(Te6edf3ChannelSettingsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72setTb4b4b4(Te6edf3indexTb4b4b4, Te6edf3settingsTb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3index Tff7b72= Te6edf3responseTb4b4b4.Te6edf3index
Tff7b72if Tb4b4b4(Te6edf3index Tff7b72+ T79c0ff1 Tff7b72< Te6edf3maxChannels Tff7b72&Tff7b72& Te6edf3route Tff7b72=Tff7b72= Te6edf3ConfigRouteTb4b4b4.Te6edf3CHANNELSTb4b4b4.Te6edf3nameTb4b4b4) Tb4b4b4{
T8b949e// Not done yet, request next channel
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffgetNextChannelTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3radioConfigUseCaseTb4b4b4.Te6edf3getChannelTb4b4b4(Te6edf3destNumTb4b4b4, Te6edf3index Tff7b72+ T79c0ff1Tb4b4b4, Te6edf3onRequestId Tff7b72= Tff7b72::Te6edf3registerRequestIdTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Received last channel, update total and start channel editor
Te6edf3setResponseStateTotalTb4b4b4(Te6edf3responseTb4b4b4.Te6edf3index Tff7b72+ T79c0ff1Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3Owner Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3userConfig Tff7b72= Te6edf3resultTb4b4b4.Te6edf3userTb4b4b4) Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3ConfigResponse Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3response Tff7b72= Te6edf3resultTb4b4b4.Te6edf3config
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3radioConfig Tff7b72=
Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3device Tff7b72= Te6edf3responseTb4b4b4.Te6edf3device Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3deviceTb4b4b4,
Te6edf3position Tff7b72= Te6edf3responseTb4b4b4.Te6edf3position Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3positionTb4b4b4,
Te6edf3power Tff7b72= Te6edf3responseTb4b4b4.Te6edf3power Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3powerTb4b4b4,
Te6edf3network Tff7b72= Te6edf3responseTb4b4b4.Te6edf3network Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3networkTb4b4b4,
Te6edf3display Tff7b72= Te6edf3responseTb4b4b4.Te6edf3display Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3displayTb4b4b4,
Te6edf3lora Tff7b72= Te6edf3responseTb4b4b4.Te6edf3lora Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3loraTb4b4b4,
Te6edf3bluetooth Tff7b72= Te6edf3responseTb4b4b4.Te6edf3bluetooth Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3bluetoothTb4b4b4,
Te6edf3security Tff7b72= Te6edf3responseTb4b4b4.Te6edf3security Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3radioConfigTb4b4b4.Te6edf3securityTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3ModuleConfigResponse Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3response Tff7b72= Te6edf3resultTb4b4b4.Te6edf3config
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3state Tff7b72-Tff7b72>
Te6edf3stateTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3moduleConfig Tff7b72=
Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3mqtt Tff7b72= Te6edf3responseTb4b4b4.Te6edf3mqtt Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3mqttTb4b4b4,
Te6edf3serial Tff7b72= Te6edf3responseTb4b4b4.Te6edf3serial Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3serialTb4b4b4,
Te6edf3external_notification Tff7b72=
Te6edf3responseTb4b4b4.Te6edf3external_notification Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3external_notificationTb4b4b4,
Te6edf3store_forward Tff7b72= Te6edf3responseTb4b4b4.Te6edf3store_forward Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3store_forwardTb4b4b4,
Te6edf3range_test Tff7b72= Te6edf3responseTb4b4b4.Te6edf3range_test Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3range_testTb4b4b4,
Te6edf3telemetry Tff7b72= Te6edf3responseTb4b4b4.Te6edf3telemetry Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3telemetryTb4b4b4,
Te6edf3canned_message Tff7b72= Te6edf3responseTb4b4b4.Te6edf3canned_message Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3canned_messageTb4b4b4,
Te6edf3audio Tff7b72= Te6edf3responseTb4b4b4.Te6edf3audio Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3audioTb4b4b4,
Te6edf3remote_hardware Tff7b72= Te6edf3responseTb4b4b4.Te6edf3remote_hardware Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3remote_hardwareTb4b4b4,
Te6edf3neighbor_info Tff7b72= Te6edf3responseTb4b4b4.Te6edf3neighbor_info Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3neighbor_infoTb4b4b4,
Te6edf3ambient_lighting Tff7b72= Te6edf3responseTb4b4b4.Te6edf3ambient_lighting Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3ambient_lightingTb4b4b4,
Te6edf3detection_sensor Tff7b72= Te6edf3responseTb4b4b4.Te6edf3detection_sensor Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3detection_sensorTb4b4b4,
Te6edf3paxcounter Tff7b72= Te6edf3responseTb4b4b4.Te6edf3paxcounter Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3paxcounterTb4b4b4,
Te6edf3statusmessage Tff7b72= Te6edf3responseTb4b4b4.Te6edf3statusmessage Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3statusmessageTb4b4b4,
Te6edf3tak Tff7b72= Te6edf3responseTb4b4b4.Te6edf3tak Tff7b72?: Te6edf3stateTb4b4b4.Te6edf3moduleConfigTb4b4b4.Te6edf3takTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3CannedMessages Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3cannedMessageMessages Tff7b72= Te6edf3resultTb4b4b4.Te6edf3messagesTb4b4b4) Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3Ringtone Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3ringtone Tff7b72= Te6edf3resultTb4b4b4.Te6edf3ringtoneTb4b4b4) Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3ConnectionStatus Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3_radioConfigStateTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3deviceConnectionStatus Tff7b72= Te6edf3resultTb4b4b4.Te6edf3statusTb4b4b4) Tb4b4b4}
Te6edf3incrementCompletedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e// Routing ACKs (Success) share the same request_id as the upcoming ADMIN_APP response.
T8b949e// Removing the id here would cause the actual admin response to be silently dropped,
T8b949e// because processRadioResponseUseCase checks `request_id in requestIds`.
T8b949e// The Success branch already handles its own id removal when route is empty (set flow).
Tff7b72if Tb4b4b4(Te6edf3result Tff7b72is Te6edf3RadioResponseResultTb4b4b4.Te6edf3SuccessTb4b4b4) Tff7b72return
Tff7b72if Tb4b4b4(Te6edf3AdminRouteTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3name Tff7b72=Tff7b72= Te6edf3route Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3sendAdminRequestTb4b4b4(Te6edf3destNumTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3requestId Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decodedTff7b72?.Te6edf3request_id Tff7b72?: Tff7b72return
T8b949e// Defer the removal so a chain continuation launched above (e.g. the next getChannel of a
T8b949e// sequential channel fetch) registers its request id first — launches run FIFO on the main
T8b949e// dispatcher, and registration is the continuation's first act before its send. Removing inline
T8b949e// would observe a momentarily-empty request set in the gap between chained requests and tear the
T8b949e// whole flow down (clearPacketResponse), stranding the rest of the chain.
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffcompletePacketResponseTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3removeRequestIdTb4b4b4(Te6edf3requestIdTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3requestIdsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3routeTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Tff7b72!Te6edf3AdminRouteTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3name Tff7b72=Tff7b72= Te6edf3route Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3clearPacketResponseTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3routeTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3completeSetRequestOrProgressBatchTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72internal Tff7b72data Tff7b72class T56d364ManualChannelUpdateResultTb4b4b4(Tff7b72val Te6edf3packetIdsTb4b4b4: Te6edf3ListTff7b72<Tffa657IntTff7b72>Tb4b4b4, Tff7b72val Te6edf3finalSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4)
Tff7b72internal Tff7b72data Tff7b72class T56d364InterruptedManualChannelUpdateTb4b4b4(
Tff7b72val Te6edf3appliedSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Tff7b72val Te6edf3appliedWriteCountTb4b4b4: Tffa657IntTb4b4b4,
Tb4b4b4)
Tff7b72internal Tff7b72suspend Tff7b72fun Td2a8ffapplyManualChannelUpdatePlanTb4b4b4(
Te6edf3updatePlanTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelTff7b72>Tb4b4b4,
Te6edf3currentSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Te6edf3finalSettingsTb4b4b4: Te6edf3ListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4,
Te6edf3writeChannelTb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3ChannelTb4b4b4, Te6edf3onRequestIdTb4b4b4: Tb4b4b4(Tffa657IntTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4) Tff7b72-Tff7b72> Tffa657IntTb4b4b4,
Te6edf3registerRequestIdTb4b4b4: Tb4b4b4(Tffa657IntTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Te6edf3onInterruptedTb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3InterruptedManualChannelUpdateTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3writeDelayTb4b4b4: Te6edf3Duration Tff7b72= Te6edf3MANUAL_CHANNEL_WRITE_DELAYTb4b4b4,
Te6edf3delayFnTb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3DurationTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tff7b72= Tb4b4b4{ Te6edf3delayTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3ManualChannelUpdateResult Tb4b4b4{
Tff7b72val Te6edf3packetIds Tff7b72= Te6edf3mutableListOfTff7b72<Tffa657IntTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3appliedSettings Tff7b72= Te6edf3currentSettingsTb4b4b4.Te6edf3toMutableListTb4b4b4(Tb4b4b4)
Tff7b72var Te6edf3appliedWriteCount Tff7b72= T79c0ff0
Tff7b72var Te6edf3updateComplete Tff7b72= Tff7b72false
Tff7b72try Tb4b4b4{
Tff7b72for Tb4b4b4(Tb4b4b4(Te6edf3indexTb4b4b4, Te6edf3channelTb4b4b4) Tff7b72in Te6edf3updatePlanTb4b4b4.Te6edf3withIndexTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// Register before the write is issued: the local loopback response/ACK can arrive
T8b949e// before the suspending send returns, so post-hoc registration would drop it.
Te6edf3writeChannelTb4b4b4(Te6edf3channelTb4b4b4) Tb4b4b4{ Te6edf3packetId Tff7b72-Tff7b72>
Te6edf3packetIdsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3packetIdTb4b4b4)
Te6edf3registerRequestIdTb4b4b4(Te6edf3packetIdTb4b4b4)
Tb4b4b4}
Te6edf3appliedSettingsTb4b4b4.Te6edf3applyManualChannelWriteTb4b4b4(Te6edf3channelTb4b4b4)
Te6edf3appliedWriteCountTff7b72+Tff7b72+
Tff7b72if Tb4b4b4(Te6edf3index Tff7b72< Te6edf3updatePlanTb4b4b4.Te6edf3lastIndexTb4b4b4) Tb4b4b4{
Te6edf3delayFnTb4b4b4(Te6edf3writeDelayTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3updateComplete Tff7b72= Tff7b72true
Tb4b4b4} Tff7b72finally Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3updateComplete Tff7b72&Tff7b72& Te6edf3appliedWriteCount Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3onInterruptedTb4b4b4(
Te6edf3InterruptedManualChannelUpdateTb4b4b4(
Te6edf3appliedSettings Tff7b72= Te6edf3appliedSettingsTb4b4b4.Te6edf3toListTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3appliedWriteCount Tff7b72= Te6edf3appliedWriteCountTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3ManualChannelUpdateResultTb4b4b4(Te6edf3packetIds Tff7b72= Te6edf3packetIdsTb4b4b4, Te6edf3finalSettings Tff7b72= Te6edf3finalSettingsTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffMutableListTff7b72<Te6edf3ChannelSettingsTff7b72>Tb4b4b4.Te6edf3applyManualChannelWriteTb4b4b4(Te6edf3channelTb4b4b4: Te6edf3ChannelTb4b4b4) Tb4b4b4{
Tff7b72while Tb4b4b4(Te6edf3size Tff7b72<Tff7b72= Te6edf3channelTb4b4b4.Te6edf3indexTb4b4b4) Tb4b4b4{
Te6edf3addTb4b4b4(Te6edf3ChannelSettingsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72thisTff7b72[Te6edf3channelTb4b4b4.Te6edf3indexTff7b72] Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3channelTb4b4b4.Te6edf3role Tff7b72=Tff7b72= Te6edf3ChannelTb4b4b4.Te6edf3RoleTb4b4b4.Te6edf3DISABLEDTb4b4b4) Tb4b4b4{
Te6edf3ChannelSettingsTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3channelTb4b4b4.Te6edf3settings Tff7b72?: Te6edf3ChannelSettingsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffHashSetTff7b72<Tffa657IntTff7b72>Tb4b4b4.Te6edf3withPacketIdTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3HashSetTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3HashSetTb4b4b4(Tff7b72thisTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3addTb4b4b4(Te6edf3packetIdTb4b4b4) Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffHashSetTff7b72<Tffa657IntTff7b72>Tb4b4b4.Te6edf3withoutPacketIdTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3HashSetTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3HashSetTb4b4b4(Tff7b72thisTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3removeTb4b4b4(Te6edf3packetIdTb4b4b4) Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffHashSetTff7b72<Tffa657IntTff7b72>Tb4b4b4.Te6edf3withoutPacketIdsTb4b4b4(Te6edf3packetIdsTb4b4b4: Te6edf3SetTff7b72<Tffa657IntTff7b72>Tb4b4b4)Tb4b4b4: Te6edf3HashSetTff7b72<Tffa657IntTff7b72> Tff7b72=
Te6edf3HashSetTb4b4b4(Tff7b72thisTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3removeAllTb4b4b4(Te6edf3packetIdsTb4b4b4) Tb4b4b4}
T8b949e/**
* Coarse mirror of firmware `AdminModule::handleSetConfig`'s reboot decision for the section being saved. Sections with
* field-level carve-outs map to [RebootBehavior.MAY_RESTART]; see [RebootBehavior] for why this stays coarse.
*/
Tff7b72internal Tff7b72fun Te6edf3ConfigTb4b4b4.Td2a8ffsaveRebootBehaviorTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3RebootBehavior Tff7b72= Tff7b72when Tb4b4b4{
Te6edf3position Tff7b72!Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3network Tff7b72!Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3bluetooth Tff7b72!Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3security Tff7b72!Tff7b72= Tff7b72null Tff7b72-Tff7b72> Te6edf3RebootBehaviorTb4b4b4.Te6edf3ALWAYS
Tff7b72else Tff7b72-Tff7b72> Te6edf3RebootBehaviorTb4b4b4.Te6edf3MAY_RESTART
Tb4b4b4}
T8b949e/** Firmware `AdminModule::handleSetModuleConfig` reboots for every module section except status message. */
Tff7b72internal Tff7b72fun Te6edf3ModuleConfigTb4b4b4.Td2a8ffsaveRebootBehaviorTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3RebootBehavior Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3statusmessage Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Te6edf3RebootBehaviorTb4b4b4.Te6edf3NEVER Tff7b72else Te6edf3RebootBehaviorTb4b4b4.Te6edf3ALWAYS
Served by rngit 1.5.0 - Generated in 0.26s